From: kaf24@firebug.cl.cam.ac.uk Date: Thu, 29 Sep 2005 12:05:43 +0000 (+0100) Subject: VIRQs and IPIs on VCPU#0 are automatically re-bound on save/restore. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16769^2~12 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=434a7023bea4eb0789d234aeac00461f7d39a84e;p=xen.git VIRQs and IPIs on VCPU#0 are automatically re-bound on save/restore. Signed-off-by: Keir Fraser --- diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c index 56729ce885..5e5ccc8d19 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smp.c @@ -131,21 +131,9 @@ DECLARE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]); static inline void __send_IPI_one(unsigned int cpu, int vector) { - unsigned int evtchn; - - evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; - // printk("send_IPI_mask_bitmask cpu %d vector %d evtchn %d\n", cpu, vector, evtchn); - if (evtchn) { -#if 0 - shared_info_t *s = HYPERVISOR_shared_info; - while (synch_test_bit(evtchn, &s->evtchn_pending[0]) || - synch_test_bit(evtchn, &s->evtchn_mask[0])) - ; -#endif - notify_via_evtchn(evtchn); - } else - printk("send_IPI to unbound port %d/%d", - cpu, vector); + int evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; + BUG_ON(evtchn < 0); + notify_via_evtchn(evtchn); } void __send_IPI_shortcut(unsigned int shortcut, int vector) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c index 793977fbd6..4642ddd1ad 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c @@ -836,13 +836,6 @@ void start_hz_timer(void) cpu_clear(smp_processor_id(), nohz_cpu_mask); } -void time_suspend(void) -{ - /* nothing */ - teardown_irq(per_cpu(timer_irq, 0), &irq_timer); - unbind_virq_from_irq(VIRQ_TIMER); -} - /* No locking required. We are only CPU running, and interrupts are off. */ void time_resume(void) { @@ -854,9 +847,6 @@ void time_resume(void) per_cpu(processed_system_time, 0) = processed_system_time; update_wallclock(); - - per_cpu(timer_irq, 0) = bind_virq_to_irq(VIRQ_TIMER); - (void)setup_irq(per_cpu(timer_irq, 0), &irq_timer); } #ifdef CONFIG_SMP diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c index 02631a176b..1f94775476 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c @@ -78,22 +78,28 @@ static u32 cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/32]; cpu_evtchn_mask[cpu][idx] & \ ~(sh)->evtchn_mask[idx]) -void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) +static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) { clear_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu_evtchn[chn]]); set_bit(chn, (unsigned long *)cpu_evtchn_mask[cpu]); cpu_evtchn[chn] = cpu; } +static void init_evtchn_cpu_bindings(void) +{ + /* By default all event channels notify CPU#0. */ + memset(cpu_evtchn, 0, sizeof(cpu_evtchn)); + memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); +} + #else #define active_evtchns(cpu,sh,idx) \ ((sh)->evtchn_pending[idx] & \ ~(sh)->evtchn_mask[idx]) +#define bind_evtchn_to_cpu(chn,cpu) ((void)0) +#define init_evtchn_cpu_bindings() ((void)0) -void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) -{ -} #endif /* Upcall to generic IRQ layer. */ @@ -244,7 +250,7 @@ int bind_ipi_to_irq(int ipi) spin_lock(&irq_mapping_update_lock); - if ((evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == 0) { + if ((evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == -1) { op.cmd = EVTCHNOP_bind_ipi; BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); evtchn = op.u.bind_ipi.port; @@ -287,7 +293,7 @@ void unbind_ipi_from_irq(int ipi) bind_evtchn_to_cpu(evtchn, 0); evtchn_to_irq[evtchn] = -1; irq_to_evtchn[irq] = -1; - per_cpu(ipi_to_evtchn, cpu)[ipi] = 0; + per_cpu(ipi_to_evtchn, cpu)[ipi] = -1; } spin_unlock(&irq_mapping_update_lock); @@ -608,41 +614,32 @@ void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) synch_set_bit(evtchn, &s->evtchn_pending[0]); } -void irq_suspend(void) -{ - int pirq, virq, irq, evtchn; - int cpu = smp_processor_id(); /* XXX */ - - /* Unbind VIRQs from event channels. */ - for (virq = 0; virq < NR_VIRQS; virq++) { - if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) - continue; - evtchn = irq_to_evtchn[irq]; - - /* Mark the event channel as unused in our table. */ - evtchn_to_irq[evtchn] = -1; - irq_to_evtchn[irq] = -1; - } - - /* Check that no PIRQs are still bound. */ - for (pirq = 0; pirq < NR_PIRQS; pirq++) - if ((evtchn = irq_to_evtchn[pirq_to_irq(pirq)]) != -1) - panic("Suspend attempted while PIRQ %d bound " - "to evtchn %d.\n", pirq, evtchn); -} - void irq_resume(void) { evtchn_op_t op; - int virq, irq, evtchn; - int cpu = smp_processor_id(); /* XXX */ + int cpu, pirq, virq, ipi, irq, evtchn; + + init_evtchn_cpu_bindings(); /* New event-channel space is not 'live' yet. */ for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++) mask_evtchn(evtchn); + /* Check that no PIRQs are still bound. */ + for (pirq = 0; pirq < NR_PIRQS; pirq++) + BUG_ON(irq_to_evtchn[pirq_to_irq(pirq)] != -1); + + /* Secondary CPUs must have no VIRQ or IPI bindings. */ + for (cpu = 1; cpu < NR_CPUS; cpu++) { + for (virq = 0; virq < NR_VIRQS; virq++) + BUG_ON(per_cpu(virq_to_irq, cpu)[virq] != -1); + for (ipi = 0; ipi < NR_IPIS; ipi++) + BUG_ON(per_cpu(ipi_to_evtchn, cpu)[ipi] != -1); + } + + /* Primary CPU: rebind VIRQs automatically. */ for (virq = 0; virq < NR_VIRQS; virq++) { - if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) + if ((irq = per_cpu(virq_to_irq, 0)[virq]) == -1) continue; /* Get a new binding from Xen. */ @@ -652,7 +649,27 @@ void irq_resume(void) evtchn = op.u.bind_virq.port; /* Record the new mapping. */ - bind_evtchn_to_cpu(evtchn, 0); + evtchn_to_irq[evtchn] = irq; + irq_to_evtchn[irq] = evtchn; + + /* Ready for use. */ + unmask_evtchn(evtchn); + } + + /* Primary CPU: rebind IPIs automatically. */ + for (ipi = 0; ipi < NR_IPIS; ipi++) { + if ((evtchn = per_cpu(ipi_to_evtchn, 0)[ipi]) == -1) + continue; + + irq = evtchn_to_irq[evtchn]; + evtchn_to_irq[evtchn] = -1; + + /* Get a new binding from Xen. */ + op.cmd = EVTCHNOP_bind_ipi; + BUG_ON(HYPERVISOR_event_channel_op(&op) != 0); + evtchn = op.u.bind_ipi.port; + + /* Record the new mapping. */ evtchn_to_irq[evtchn] = irq; irq_to_evtchn[irq] = evtchn; @@ -670,15 +687,15 @@ void __init init_IRQ(void) spin_lock_init(&irq_mapping_update_lock); -#ifdef CONFIG_SMP - /* By default all event channels notify CPU#0. */ - memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); -#endif + init_evtchn_cpu_bindings(); for (cpu = 0; cpu < NR_CPUS; cpu++) { /* No VIRQ -> IRQ mappings. */ for (i = 0; i < NR_VIRQS; i++) per_cpu(virq_to_irq, cpu)[i] = -1; + /* No VIRQ -> IRQ mappings. */ + for (i = 0; i < NR_IPIS; i++) + per_cpu(ipi_to_evtchn, cpu)[i] = -1; } /* No event-channel -> IRQ mappings. */ diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index b3d6874b0a..03fff886aa 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -74,16 +74,12 @@ static int __do_suspend(void *ignore) extern int gnttab_suspend(void); extern int gnttab_resume(void); - extern void time_suspend(void); extern void time_resume(void); extern unsigned long max_pfn; extern unsigned long *pfn_to_mfn_frame_list_list; extern unsigned long *pfn_to_mfn_frame_list[]; #ifdef CONFIG_SMP - extern void smp_suspend(void); - extern void smp_resume(void); - static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; cpumask_t prev_online_cpus, prev_present_cpus; @@ -156,18 +152,10 @@ static int __do_suspend(void *ignore) kmem_cache_shrink(pgd_cache); #endif - time_suspend(); - -#ifdef CONFIG_SMP - smp_suspend(); -#endif - xenbus_suspend(); xencons_suspend(); - irq_suspend(); - gnttab_suspend(); HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; @@ -212,10 +200,6 @@ static int __do_suspend(void *ignore) xenbus_resume(); -#ifdef CONFIG_SMP - smp_resume(); -#endif - time_resume(); usbif_resume(); diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c index 139ce282d8..807f0fd9b4 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c @@ -31,14 +31,9 @@ DECLARE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]); static inline void __send_IPI_one(unsigned int cpu, int vector) { - unsigned int evtchn; - Dprintk("%s\n", __FUNCTION__); - - evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; - if (evtchn) - notify_via_evtchn(evtchn); - else - printk("send_IPI to unbound port %d/%d", cpu, vector); + int evtchn = per_cpu(ipi_to_evtchn, cpu)[vector]; + BUG_ON(evtchn < 0); + notify_via_evtchn(evtchn); } void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h index f4cde5f102..49e5ac07f0 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h @@ -80,11 +80,9 @@ * the usable vector space is 0x20-0xff (224 vectors) */ -#define NR_IPIS 8 - -#define RESCHEDULE_VECTOR 1 -#define INVALIDATE_TLB_VECTOR 2 -#define CALL_FUNCTION_VECTOR 3 +#define RESCHEDULE_VECTOR 0 +#define CALL_FUNCTION_VECTOR 1 +#define NR_IPIS 2 /* * The maximum number of vectors supported by i386 processors diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h index 690560c823..c7d85b1967 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h @@ -78,11 +78,9 @@ * the usable vector space is 0x20-0xff (224 vectors) */ -#define NR_IPIS 8 - -#define RESCHEDULE_VECTOR 1 -#define INVALIDATE_TLB_VECTOR 2 -#define CALL_FUNCTION_VECTOR 3 +#define RESCHEDULE_VECTOR 0 +#define CALL_FUNCTION_VECTOR 1 +#define NR_IPIS 2 /* * The maximum number of vectors supported by i386 processors diff --git a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h index e60155206b..d364b0a4b5 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h @@ -68,7 +68,6 @@ extern int bind_evtchn_to_irqhandler( void *dev_id); extern void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id); -extern void irq_suspend(void); extern void irq_resume(void); /* Entry point for notifications into Linux subsystems. */